/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.documentar.init;

import br.com.documentar.DAO.VersionamentoDAO;
import br.com.documentar.model.VersionamentoModel;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 *
 * @author Santos
 */
public class CheckBoot {

    /**
     * *
     * criar toda a estrutura de pasta que está faltando para o sistema
     * funcionar
     */
    private br.com.documentar.model.ConfigBancoDadosModel model = new br.com.documentar.model.ConfigBancoDadosModel();
    private String host;
    private String porta;
    private String banco;
    private String opcaoBancoDados;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getPorta() {
        return porta;
    }

    public void setPorta(String porta) {
        this.porta = porta;
    }

    public String getBanco() {
        return banco;
    }

    public void setBanco(String banco) {
        this.banco = banco;
    }

    public String getOpcaoBancoDados() {
        return opcaoBancoDados;
    }

    public void setOpcaoBancoDados(String opcaoBancoDados) {
        this.opcaoBancoDados = opcaoBancoDados;
    }

    /**
     * *
     * Construtor da classe, é inicializado quando a classe é instanciada
     */
    public CheckBoot() {
    }

    /**
     * Verifica se a pasta e arquivo de configuração existem, caso não será
     * aberta uma janela para fazer a configuração
     *
     *
     * @return True(Confugração Ok) ou False (Desconfigurado)
     */
    public boolean VerificarArquivoConfigBancoDados() {

        //armazena caminho da pasta
        File dir1 = new File(ReturnWayFolderConfigDataBase(ReturnWayNow()));
        File dir2 = new File(dir1.getAbsolutePath());

        if (dir2.exists()) {
            File dir3 = new File(ReturnWayFileConfigDataBase());
            if (dir3.exists()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * Metodo retorna o caminho onde o arquivo .jar está sendo executado
     *
     * @return Caminho onde está sendo executado o arquivo
     */
    public String ReturnWayNow() {
        return System.getProperty("user.dir");
    }

    /**
     * Metodo retorna de execução do arquivo mais a pasta de configuração do
     * banco de dados
     *
     * @param caminhoAtual Caminho onde está executando o programa. Deve-se
     * passar o metodo (ReturnWayNow).
     * @return Caminho do arquivo de configuração do banco de dados
     */
    public String ReturnWayFolderConfigDataBase(String caminhoAtual) {
        return (caminhoAtual + model.getPASTA_ARQUIVO_CONFIG());
    }

    /**
     * Metodo retorna o caminho exato do arquivo de configuração de acesso ao
     * banco de dados
     *
     * @return Caminho do arquivo de configuração de acesso ao Banco de dados
     */
    public String ReturnWayFileConfigDataBase() {
        return ReturnWayFolderConfigDataBase(ReturnWayNow()) + model.getNOME_ARQUIVO_CONFIG_BANCO_DADOS();
    }

    /**
     * Metodo criar o arquivo de configuração para acesso ao banco de dados
     *
     * @param model
     * @return Retorna True se teve sucesso ou False se não teve sucesso na
     * criação do arquivo
     */
    public boolean createFileConfig(br.com.documentar.model.ConfigBancoDadosModel model) {
        try {
            File f = new File(ReturnWayFileConfigDataBase());
            f.delete();
            f.createNewFile();
            try (FileWriter f6 = new FileWriter(f, false); PrintWriter f7 = new PrintWriter(f6)) {
                f7.println(model.getOpcaoBancoDados());
                f7.println(model.getHost());
                f7.println(model.getBanco());
                f7.println(model.getPorta());
            }
            return true;
        } catch (IOException ex) {
            Logger.getLogger(CheckBoot.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
    }

    /**
     * Metodo responsável por fazer a leitura do arquivo com os dados de conexão
     * com banco de dados
     *
     * @return True se conseguir ler o arquivo sem erro ou False se não
     * conseguir ler o arquivo
     */
    public boolean ReadFileConnect() {
        try {
            FileInputStream in = new FileInputStream(ReturnWayFileConfigDataBase());
            Scanner scanner = new Scanner(in);
            while (scanner.hasNext()) {
                setOpcaoBancoDados(scanner.nextLine());
                setHost(scanner.nextLine());
                setBanco(scanner.nextLine());
                setPorta(scanner.nextLine());
            }
        } catch (FileNotFoundException e) {
            e.getMessage();
            return false;
        }
        return true;
    }

    /**
     * Metodo responsável por verificar se a versão do banco de dados é
     * compatível com a versão do executável
     *
     * @return
     */
    public boolean testarVersao() {

        try {
            VersionamentoModel teste;
            teste = lerXmlVersao();
            VersionamentoModel modelVersionamento = new VersionamentoModel();
            modelVersionamento.setActionScript("C");
            VersionamentoDAO daoVersionamento = new VersionamentoDAO();
            daoVersionamento.getDados(modelVersionamento);
            return modelVersionamento.getVersionamento(teste.getCodigo(), teste.getNome()) != null;

        } catch (Exception ex) {
            Logger.getLogger(CheckBoot.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
    }

    /**
     * Metodo responsável por fazer a leitura do XML e retornar um model com os
     * dados
     *
     * @return
     * @throws Exception
     */
    private VersionamentoModel lerXmlVersao() throws Exception {
        VersionamentoModel versionamentoModel = new VersionamentoModel();
        try {

            String uri = "VersionamentoXML.xml";
            InputStream is = getClass().getResourceAsStream(uri);
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(is);

            Element elem = doc.getDocumentElement();

            // pega todos os elementos usuario do XML  
            NodeList nl = elem.getElementsByTagName("versao");
            Element tagVersao = (Element) nl.item(0);
            // pega os dados cadastrado para o usuario atual  
            versionamentoModel.setCodigo(Integer.parseInt(getChildTagValue(tagVersao, "id")));
            versionamentoModel.setNome(getChildTagValue(tagVersao, "nome"));

        } catch (ParserConfigurationException | SAXException | IOException ex) {
            ex.getStackTrace();
        }
        return versionamentoModel;
    }

    /**
     * este método lê e retorna o conteúdo (texto) de uma tag (elemento) filho
     * da tag informada como parâmetro. A tag filho a ser pesquisada é a tag
     * informada pelo nome (string)
     */
    private String getChildTagValue(Element elem, String tagName) throws Exception {
        NodeList children = elem.getElementsByTagName(tagName);
        if (children == null) {
            return null;
        }
        Element child = (Element) children.item(0);
        if (child == null) {
            return null;
        }
        return child.getFirstChild().getNodeValue();
    }

}
